;;; guile-openai --- An OpenAI API client for Guile
;;; Copyright © 2023 Andrew Whatson <whatson@tailcall.au>
;;;
;;; This file is part of guile-openai.
;;;
;;; guile-openai is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU Affero General Public License as
;;; published by the Free Software Foundation, either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; guile-openai is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Affero General Public License for more details.
;;;
;;; You should have received a copy of the GNU Affero General Public
;;; License along with guile-openai.  If not, see
;;; <https://www.gnu.org/licenses/>.

(define-module (openai moderation)
  #:use-module (openai api moderation)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-9)
  #:export (openai-default-moderation-model

            moderation?
            moderation-flagged?
            moderation-categories
            moderation-scores
            moderation-score

            openai-moderation))

(define-once openai-default-moderation-model
  (make-parameter *unspecified*))

(define-record-type <Moderation>
  (%make-moderation flagged? categories scores)
  moderation?
  (flagged? moderation-flagged?)
  (categories moderation-categories)
  (scores moderation-scores))

(define (make-moderation response)
  (let ((result (car (moderation-response-results response))))
    (%make-moderation
     (moderation-result-flagged? result)
     (filter-map (match-lambda
                   ((category . true?)
                    (and true? (string->symbol category))))
                 (moderation-result-categories result))
     (map (match-lambda
            ((category . score)
             (cons (string->symbol category) score)))
          (moderation-result-category-scores result)))))

(define (moderation-score moderation category)
  (assq-ref (moderation-scores moderation) category))

(define* (openai-moderation input #:optional
                            (model (openai-default-moderation-model)))
  "Send a moderation request.  Returns a moderation record.

The INPUT must be a string to be classified by the moderation model.

The keyword arguments correspond to the request parameters described
in the moderation request documentation:

#:model - A symbol or string identifying the model to use.  The
default is unspecified, which is equivalent to
`text-moderation-latest'."
  (let* ((model (if (symbol? model) (symbol->string model) model))
         (request (make-moderation-request input model))
         (response (send-moderation-request request)))
    (make-moderation response)))
